Skip to content

feat(kyc-controller): publish verificationStatusChanged for analytics - #11041

Merged
georgeweiler merged 11 commits into
mainfrom
gw/kyc-verification-events
Oct 27, 2026
Merged

georgeweiler merged 11 commits into
mainfrom
gw/kyc-verification-events

Conversation

@georgeweiler

@georgeweiler georgeweiler commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Explanation

Mobile needs KYC analytics (schema: Consensys/segment-schema#785) in two shapes. The controller calls an optional trackKycAnalytics constructor callback after the state write (a crash can lose a call but never duplicates one). Clients that do not track omit the option. Nothing is added to KycControllerEvents.

trackKycAnalytics.verificationOutcome, payload { status, kycStatus, providerFlowStatus, vendor }: one per SumSub launch attempt in #launchSumsubFlow (submitted, abandoned, failed), even if it repeats the previous outcome. The two failed returns that never write state (session id changed while the SDK was open) also call it.

trackKycAnalytics.statusChanged, payload { previousKycStatus?, kycStatus, providerFlowStatus, vendor }: called after any session-replacing write that changes the analytics KYC status (new to pending, pending to approved, rejected, retry, ...). A submitted launch also calls this (new to pending). previousKycStatus is absent when the session was just created.

  • The analytics KYC status is the session's finalStatus (new, pending, approved, rejected, retry), or none when there is no session or the value is unknown, exposed as getKycAnalyticsStatus. It deliberately ignores the relay kycStatus and the provider flow, unlike RampsController's VBA KYC resolution, which I did not change.
  • Loading a session into an empty slot (startSession lookup fill, e.g. after a reinstall) calls neither callback, so an already-approved session is not reported as a new decision.
  • started (SumSub webview opened) and retry_started (user pressed retry) are UI moments the controller never sees, so mobile fires those itself.
  • Payloads carry no session id, email, disclaimer or token data.

Mobile passes the callbacks from kycControllerInit (MetaMask/metamask-mobile#38160). That PR still subscribes to the previous messenger events and needs to pass trackKycAnalytics instead.

References

  • Analytics schema: Consensys/segment-schema#785

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Low Risk
Additive optional constructor callbacks with try/catch isolation; core KYC state machine behavior is covered by extensive tests and unchanged when trackers are omitted.

Overview
Adds optional KYC analytics hooks on KycController via a new trackKycAnalytics constructor option (no new messenger events). Hosts pass verificationOutcome and statusChanged callbacks that run after the relevant state write.

verificationOutcome fires once per SumSub launch attempt (submitted, abandoned, failed), including repeats and failures that do not mutate state. statusChanged fires when the analytics KYC status (derived from session finalStatus via getKycAnalyticsStatus, with none for missing/unknown) actually changes—e.g. session creation, submit → pending, poll/refetch → approved/rejected/retry. Restoring a session into empty state after reinstall uses a plain state update and does not invoke either callback.

Payloads include kycStatus, providerFlowStatus, and vendor only (no session id, email, or tokens). Throwing callbacks are swallowed so KYC outcomes and polling behavior stay unchanged. The package exports analytics.ts types, KYC_ANALYTICS_STATUSES, and getKycAnalyticsStatus.

Reviewed by Cursor Bugbot for commit 785d248. Bugbot is set up for automated code reviews on this repo. Configure here.

Publish KycController:verificationStatusChanged after the state write for
each SumSub launch outcome (submitted, abandoned, failed) and when the
derived KYC status newly becomes approved (succeeded) or rejected.
Loading an already-decided session into empty state does not publish.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@georgeweiler
georgeweiler requested review from a team as code owners October 23, 2026 16:20
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…launch outcomes

verificationStatusChanged now covers only SumSub launch outcomes
(submitted, abandoned, failed). A new kycStatusChanged event is
published for any change of the derived KYC status, including
approved, rejected, retry and the move to pending after a submitted
launch.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@jiexi

jiexi commented Oct 23, 2026

Copy link
Copy Markdown
Member

My main concern right now is that these changes need to be very clearly Analytics namespaced otherwise they make it difficult to discern from the business logic types and methods

georgeweiler and others added 3 commits October 23, 2026 11:09
Rename the analytics-only API so it is clearly separate from the KYC
business logic, per review: verificationStatus.ts becomes analytics.ts,
KycDerivedStatus becomes KycAnalyticsStatus, deriveKycStatus becomes
getKycAnalyticsStatus, and the events become analyticsVerificationOutcome
and analyticsStatusChanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…methods

Rename the session-write wrappers to ...AndPublishAnalytics, group the
analytics-only private methods under an ANALYTICS banner, and document
analytics.ts as analytics-only.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…tatus only

Per review: drop the relay kycStatus and provider-flow rules. A submitted
launch already writes finalStatus pending, and a relay approval is
reported once finalStatus follows it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…lback

Analytics signals were published as KycController messenger events, which sit beside the KYC business events. Clients now pass trackKycAnalytics and the controller calls it after the same state writes.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fe01319. Configure here.

georgeweiler and others added 4 commits October 27, 2026 04:01
A throwing trackKycAnalytics callback was caught as a SumSub launch failure, which overwrote the stored outcome and could keep an approved session polling.

Co-authored-by: Cursor <cursoragent@cursor.com>
…vents

Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	packages/kyc-controller/CHANGELOG.md
Co-authored-by: Cursor <cursoragent@cursor.com>
`statusChanged` omitted `previousKycStatus` whenever the status before the
write resolved to `none`. That covers two different things: a session that
was just created, and a stored `finalStatus` outside
`KYC_ANALYTICS_STATUSES` (or a session cleared by `reset`/`clearState`).
A consumer reading an absent field as "first observation" counts the second
case as a new user, and loses the transition.

The field is now required and carries `none` in both cases.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
georgeweiler added a commit that referenced this pull request Oct 27, 2026
`refreshAutorampTransactions` wrote the record and then called
`trackAutorampTransactionStatusChanged` for each change with no guard, so a
throwing host tracker both rejected the refresh and skipped every later
change in the batch. The record already says those statuses were seen, so
they would never be reported again.

The callback is now wrapped per change, matching the `trackKycAnalytics`
callbacks on `KycController` (#11041).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@georgeweiler
georgeweiler added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit 57dc193 Oct 27, 2026
46 checks passed
@georgeweiler
georgeweiler deleted the gw/kyc-verification-events branch October 27, 2026 18:27
gaohan1994 pushed a commit to gaohan1994/core that referenced this pull request Oct 28, 2026
## Explanation

Scoped release so clients can pick up MetaMask#11017 and MetaMask#11041.

- **`@metamask/ramps-controller` 27.2.0 → 28.0.0** (major). Persists
autoramp transaction statuses and reports a new id or a changed status
string through the optional `trackAutorampTransactionStatusChanged`
callback. **BREAKING:** `RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS` now
includes `NeoBankService:listAutorampTransactions`. Hosts that spread
that list pick it up on the bump. Hosts that copy the action list by
hand must delegate it. This version also includes the unpublished
`@metamask/utils` range bump to `^12.0.1` from MetaMask#11107.
- **`@metamask/kyc-controller` 0.12.1 → 0.13.0** (minor). Adds the
optional `trackKycAnalytics` constructor callbacks
(`verificationOutcome` and `statusChanged`) from MetaMask#11041. Nothing is
added to `KycControllerEvents`. This version also includes the
unpublished `@metamask/utils` range bump to `^12.0.1` from MetaMask#11107.
- **`@metamask/transaction-pay-controller` 30.3.0 → 30.3.1** (patch).
Published because `ramps-controller` is a major and this is its only
workspace dependent. The range moves from `^27.2.0` to `^28.0.0`.

Other packages with unreleased changes are deferred.

## References

- Ships MetaMask#11017
- Ships MetaMask#11041
- Also publishes the unpublished utils range bump already on main:
MetaMask#11107

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them


Made with [Cursor](https://cursor.com)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> The ramps-controller major adds a required messenger action for
autoramp transaction polling; hosts that hand-maintain delegated actions
must update or delegation fails at runtime.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2be3977. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
darkwing pushed a commit to darkwing/metamask-mobile that referenced this pull request Oct 29, 2026
…ask#38322)

## **Description**

Adopts the two controller releases that the VBA / KYC analytics work
depends on, and nothing else. No app behaviour changes.

- `@metamask/kyc-controller` `^0.12.0` → `^0.13.0`
- `@metamask/ramps-controller` `^27.1.0` → `^28.0.0`

This is deliberately split out from the three analytics PRs that consume
these APIs
([MetaMask#38078](MetaMask#38078),
[MetaMask#38160](MetaMask#38160),
[MetaMask#38161](MetaMask#38161)) for
four reasons:

1. **`ramps-controller` is a major bump** (27.1.0 → 28.0.0, also
skipping 27.2.0). That is a Ramps/platform review, not an analytics
review, and it should not be buried in a PR about Segment events.
2. **One lockfile change instead of three.** If each analytics PR
bumped, whichever merged first would force the other two to re-resolve
`yarn.lock`.
3. **It makes the analytics PRs verifiable.** All three currently
reference APIs that did not exist in the installed versions, so none of
them can produce a meaningful `lint:tsc` result until this lands.
4. **Revert safety.** If the bump regresses something unrelated, it
reverts on its own.

### The breaking change is a no-op for us

`ramps-controller@28.0.0` has one breaking change:

> **BREAKING:** `RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS` now includes
`NeoBankService:listAutorampTransactions`. Hosts must delegate that
action to `RampsController`.

No code change is needed here.
[`ramps-controller-messenger.ts`](https://github.com/MetaMask/metamask-mobile/blob/main/app/core/Engine/messengers/ramps-controller-messenger/ramps-controller-messenger.ts#L47)
already spreads the package-owned list rather than enumerating actions:

```ts
actions: [
  // Spread the package-owned required list so new service actions
  // (e.g. getDefaultRedirectCallbackUrl / NeoBankService) cannot be
  // forgotten at upgrade.
  ...RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS,
  ...
],
```

and `NeoBankService` is registered as a messenger client in `Engine.ts`,
so the new action is delegated automatically.

### Reviewer note: `ramps-controller` is now duplicated in the tree

`@metamask/transaction-pay-controller@30.2.0` depends on
`@metamask/ramps-controller@^27.1.0`, so this bump un-dedupes it:

```
├─ @metamask/transaction-pay-controller@npm:30.2.0
│  └─ @metamask/ramps-controller@npm:27.1.0 (via npm:^27.1.0)
└─ metamask@workspace:.
   └─ @metamask/ramps-controller@npm:28.0.0 (via npm:^28.0.0)
```

TPC references ramps in its messenger types
(`RampsControllerGetOrderAction`,
`RampsControllerGetQuoteWithFeesAction`). Those action shapes are
unchanged in 28.0.0 — the only breaking change was the constant above —
and `lint:tsc` passes, so this is a bundle-size cost rather than a
correctness one. Flagging it so it is a conscious decision: the clean
fix is a TPC release that widens its range to `^28.0.0`, which can
follow separately.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: MetaMask/core#11017
Refs: MetaMask/core#11041
Refs: MetaMask/core#11141

## **Manual testing steps**

```gherkin
Feature: VBA and KYC flows still work on the bumped controllers

  Scenario: Autoramp transactions still load on the VBA details screen
    Given a Money account with an approved autoramp
    When the user opens the virtual bank account details screen
    Then the deposit instructions render
    And no "action not registered" error is raised for NeoBankService:listAutorampTransactions

  Scenario: KYC identity verification still launches
    Given a user part way through VBA onboarding
    When the user reaches the identity verification step
    Then the SumSub webview opens as before
    And the stored KYC status still updates when the decision arrives
```

## **Screenshots/Recordings**

N/A — dependency bump with no UI change.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable — no new code, so no new tests.
The existing ramps, KYC and ramps-messenger suites were run against the
bumped packages (12 suites, 138 tests).
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable — N/A, no new code.
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics

Not applicable: no runtime code changes. The one performance-relevant
consequence is the duplicated `ramps-controller` noted above, which is a
bundle-size effect rather than a runtime one.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Major ramps-controller bump touches VBA/autoramp and KYC-adjacent
flows; runtime wiring appears pre-covered, but regressions in money
onboarding are still possible.
> 
> **Overview**
> Dependency-only PR that upgrades **`@metamask/kyc-controller`**
(`^0.12.0` → `^0.13.0`) and **`@metamask/ramps-controller`** (`^27.1.0`
→ `^28.0.0`), with matching **`yarn.lock`** resolution. No application
logic changes beyond keeping tests aligned with the new controller
default state.
> 
> The test background snapshot adds **`autorampTransactionRecords: {}`**
under **`RampsController`**, matching new state shipped in
ramps-controller 28. **`ramps-controller-messenger.ts`** already spreads
**`RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS`**, so the 28.0 breaking
requirement to delegate **`NeoBankService:listAutorampTransactions`**
does not need a separate host change here.
> 
> This bump is split ahead of VBA/KYC analytics PRs that depend on these
package APIs. Note that **`transaction-pay-controller`** may still pull
**`ramps-controller@27.x`**, so the tree can temporarily carry two
versions until TPC widens its range.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
49c0f97. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
yashgo0018 pushed a commit to yashgo0018/metamask-mobile that referenced this pull request Oct 30, 2026
## **Description**

Fires the KYC analytics events for VBA identity verification, matching
the schema merged in Consensys/segment-schema#785 and the callback API
on MetaMask/core#11041.

- **`KYC Status Updated`.** `kycControllerInit` passes
`trackKycAnalytics.statusChanged`. `kyc_status` is the new status and
`previous_kyc_status` is the one stored before. `previous_kyc_status` is
absent the first time a status is stored. It fires for any change of the
stored status, including while polling when no screen is involved.
- **`KYC Verification Updated` (SumSub webview steps).** `submitted`,
`abandoned`, and `failed` come from
`trackKycAnalytics.verificationOutcome`, once per launch attempt.
`started` fires right before `launchProviderFlow` in `useLaunchSumSub`.
`retry_started` fires from the SumSub error-screen retry (`retry_source:
sumsub_error`) and the KYC rejected-screen retry (`retry_source:
kyc_rejected`). The controller never sees those two. `retry_source` is
sent only with `retry_started`.
- Properties come from one builder (`kycVerificationAnalytics.ts`):
`screen_name` (`vba_onboarding`), `entry_point`
(`add_funds_bank_account`), `vendor` (`moonpay`), and `kyc_provider`
(`sumsub`) are constants. `kyc_status` and `provider_flow_status` are
always sent; missing controller state uses `none` and `not_started`.
`region` is the lowercase alpha-2 country from the geolocation
controller. It is omitted while the location is unknown, because the
schema has no unknown country value. No session id, email, disclaimer,
or token data is sent.

There is no KYC analytics messenger and no `KycController` analytics
event. The controller decides when a stored status changed; mobile only
maps the payload onto Segment.

**Depends on MetaMask/core#11041** (`trackKycAnalytics`,
`getKycAnalyticsStatus`, and the payload types). The installed
`@metamask/kyc-controller` does not include the option yet, so the
constructor options are built on a variable. This PR will not fully
typecheck until a release containing that API is installed. The
dependency bump belongs here once released.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: MetaMask/core#11041, Consensys/segment-schema#785

## **Manual testing steps**

Not yet run on a device or in Segment (blocked on the core release
above). Once unblocked:

```gherkin
Feature: KYC Verification Updated analytics
  Scenario: user completes SumSub and is approved
    Given a VBA user with an open KYC session
    When the SumSub webview opens, the user submits, and polling finds the session approved
    Then KYC Verification Updated is sent for started and submitted, and KYC Status Updated is sent for the move to pending and to approved with previous_kyc_status

  Scenario: user closes SumSub early
    When the user closes the SumSub webview without submitting
    Then abandoned is sent

  Scenario: user retries
    When the user taps retry on the SumSub error screen or the KYC rejected screen
    Then retry_started is sent with the matching retry_source
```

## **Screenshots/Recordings**

N/A, analytics only.

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## **Description**

Fires the KYC analytics events for VBA identity verification, matching
the schema merged in Consensys/segment-schema#785 and the callback API
on MetaMask/core#11041.

- **`KYC Status Updated`.** `kycControllerInit` passes
`trackKycAnalytics.statusChanged`. `kyc_status` is the new status and
`previous_kyc_status` is the one stored before. `previous_kyc_status` is
always sent; `none` means nothing was stored before, including the first
time a status is stored. It fires for any change of the stored status,
including while polling when no screen is involved.
- **`KYC Verification Updated` (SumSub webview steps).** `submitted`,
`abandoned`, and `failed` come from
`trackKycAnalytics.verificationOutcome`, once per launch attempt.
`started` fires right before `launchProviderFlow` in `useLaunchSumSub`.
`retry_started` fires from the SumSub error-screen retry (`retry_source:
sumsub_error`) and the KYC rejected-screen retry (`retry_source:
kyc_rejected`). The controller never sees those two. `retry_source` is
sent only with `retry_started`.
- Properties come from one builder (`kycVerificationAnalytics.ts`):
`screen_name` (`vba_onboarding`), `entry_point`
(`add_funds_bank_account`), `vendor` (`moonpay`), and `kyc_provider`
(`sumsub`) are constants. `kyc_status` and `provider_flow_status` are
always sent; missing controller state uses `none` and `not_started`.
`region` is always sent: the lowercase alpha-2 country from the
geolocation controller, or `unknown` while the location is unresolved.
No session id, email, disclaimer, or token data is sent.

There is no KYC analytics messenger and no `KycController` analytics
event. The controller decides when a stored status changed; mobile only
maps the payload onto Segment.

**Depends on MetaMask/core#11041** (`trackKycAnalytics`,
`getKycAnalyticsStatus`, and the payload types). Merging current `main`
brings in `@metamask/kyc-controller` 0.13.0, which includes that API.
The constructor options are still built on a variable, as they were
before that release was installed.

Performance checklist items are checked as not applicable. This change
only adds analytics events and does not change screens, lists, or
traces.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: MetaMask/core#11041, Consensys/segment-schema#785

## **Manual testing steps**

Unit tests cover the event mapping. This has not been run on a device or
in Segment.

```gherkin
Feature: KYC Verification Updated analytics
  Scenario: user completes SumSub and is approved
    Given a VBA user with an open KYC session
    When the SumSub webview opens, the user submits, and polling finds the session approved
    Then KYC Verification Updated is sent for started and submitted, and KYC Status Updated is sent for the move to pending and to approved with previous_kyc_status

  Scenario: user closes SumSub early
    When the user closes the SumSub webview without submitting
    Then abandoned is sent

  Scenario: user retries
    When the user taps retry on the SumSub error screen or the KYC rejected screen
    Then retry_started is sent with the matching retry_source
```

## **Screenshots/Recordings**

N/A, analytics only.

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-6441b49b-ba6a-5174-9ab9-d5759c027458?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-6441b49b-ba6a-5174-9ab9-d5759c027458&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Analytics-only, additive instrumentation on the KYC path with
try/catch isolation and no session or PII in event properties;
user-facing verification behavior is unchanged aside from when metrics
fire.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
48177f6. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants